package cn.dsp.admin.realm;

import cn.dsp.admin.config.MyUsernamePasswordToken;
import cn.dsp.admin.entity.Permission;
import cn.dsp.admin.entity.admin.Admin;
import cn.dsp.admin.entity.admin.Role;
import cn.dsp.admin.service.IAdminService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;

public class AutuRealm extends AuthorizingRealm {
    Boolean cachingEnabled=true;

    @Autowired
    private IAdminService service;

    /**
     * 为用户授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取页面输入的用户信息，封装为Admin对象
        Admin admin = (Admin) principalCollection.getPrimaryPrincipal();
        //获取前端输入的用户名
        String adminName = admin.getAdminName();
        //根据用户名查询数据库中对应的记录
        Admin result = service.getByAdminName(adminName);
        //如果存在进行授权操作
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (result!=null){
            //因为addRoles和addStringPermissions方法需要的参数是Collection
            //所以创建两个Collection集合
            Collection<String> roleStringCollection = new HashSet<>();
            Collection<String> persCollection = new HashSet<>();
            //获取admin的Role的set集合
            Set<Role> adminRoles = new HashSet<>(admin.getRoles());

            //遍历集合
            for (Role role:adminRoles) {
                //将每个role的name装进collection集合
                roleStringCollection.add(role.getRoleName());
                //获取每一个Role的permission的set集合
                Set<Permission> permissionSet = role.getPermissions();
                //遍历集合
                for (Permission permission:permissionSet) {
                    //将每一个permission的name装进collection集合
                    persCollection.add(permission.getName());
                }
                //为用户授权
                info.addStringPermissions(persCollection);
            }
            //为用户授予角色
            info.addRoles(roleStringCollection);
            return info;
        }
        return info;
    }

    /**
     * 认证登录
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("调用认证方法！！！！");
        //token携带了用户信息
        MyUsernamePasswordToken token = (MyUsernamePasswordToken) authenticationToken;
        //获取前端输入用户名
        String username = token.getPrincipal().toString();
             String password = token.getPassword();

        //当前realm对象的name
        String realmName = this.getName();

        //根据用户查询数据库中对应的记录
        Admin admin = service.getByAdminName(username);
        if(admin==null) {
            throw new UnknownAccountException();//没找到帐号
        }
        boolean Locked = admin.getIsDelete() == 1;
        if(Boolean.TRUE.equals(Locked)){
            throw new LockedAccountException(); //帐号锁定
        }
        String saltStr = admin.getSalt();
            System.out.println("获取盐值");
        ByteSource salt = ByteSource.Util.bytes(saltStr);
            System.out.println("salt:"+salt);
            token.setSalt(saltStr);
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(admin,admin.getPassword(),realmName);
        //解盐
        //authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(salt));
        super.clearCachedAuthorizationInfo(authenticationInfo.getPrincipals());
        SecurityUtils.getSubject().getSession().setAttribute("login",admin);

            System.out.println("authInfo:"+authenticationInfo);
            System.out.println("用户输入的用户名和密码\t"+username+"\t"+ password);
        return authenticationInfo;
    }

    /**
     * 自定义的UsernamePasswordToken类
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token!=null&&(token instanceof MyUsernamePasswordToken || token instanceof UsernamePasswordToken);
    }
/**
     * 设定Password校验.
     */
   /* @PostConstruct
    public void initCredentialsMatcher() {
        System.out.println("调用密码校验");
        //该句作用是重写shiro的密码验证，让shiro用我自己的验证
        setCredentialsMatcher(new CustomCredentialsMatcher());

    }*/






}
